package com.have.blog.xo.service.admin.impl;

import com.github.pagehelper.PageHelper;
import com.have.blog.base.constant.BlogConstant;
import com.have.blog.base.enums.BlogStatus;
import com.have.blog.base.holder.RequestHolder;
import com.have.blog.commons.config.jwt.Audience;
import com.have.blog.commons.feign.PictureFeignClient;
import com.have.blog.model.api.CommonPage;
import com.have.blog.model.mapper.TAdminMapper;
import com.have.blog.model.models.TAdmin;
import com.have.blog.model.models.TAdminExample;
import com.have.blog.model.models.TRole;
import com.have.blog.utils.MyStringUtils;
import com.have.blog.utils.ResultUtils;
import com.have.blog.xo.bo.admin.OnlineAdmin;
import com.have.blog.xo.constant.MessageConstant;
import com.have.blog.xo.constant.SysConstant;
import com.have.blog.xo.service.admin.AdminAdminService;
import com.have.blog.xo.service.admin.AdminRoleService;
import com.have.blog.xo.service.cache.AdminCacheService;
import com.have.blog.xo.service.admin.SystemParamService;
import com.have.blog.xo.uitls.WebUtil;
import com.have.blog.xo.vo.AdminAdminVo;
import com.have.haveblog.security.utils.JwtTokenUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
@SuppressWarnings("all")
public class AdminAdminServiceImpl implements AdminAdminService {

    @Autowired
    private TAdminMapper adminMapper;
    @Autowired
    private SystemParamService systemParamService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AdminCacheService adminCacheService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private Audience audience;
    @Autowired
    private PictureFeignClient pictureFeignClient;
    @Autowired
    private WebUtil webUtil;
    @Autowired
    private AdminRoleService roleService;

    @Override
    public String getList(AdminAdminVo adminVo) {
        PageHelper.startPage(adminVo.getCurrentPage(), adminVo.getPageSize());
        // 1. 获取管理员实体
        TAdminExample example = new TAdminExample();
        TAdminExample.Criteria criteria1 = example.createCriteria();
        criteria1.andStatusEqualTo(BlogStatus.ENABLE.getStatus());
        if (!StringUtils.isEmpty(adminVo.getKeyword())) {
            criteria1.andUserNameLike("%" + adminVo.getKeyword() + "%");
            TAdminExample.Criteria criteria2 = example.createCriteria();
            criteria2.andNickNameLike("%" + adminVo.getKeyword() + "%");
            example.or(criteria2);
        }
        example.setOrderByClause("create_time desc");
        List<TAdmin> adminList = adminMapper.selectByExample(example);
        for (TAdmin admin : adminList) {
            admin.setPassWord(null);
        }

//         2. 获取UID与头像
        final StringBuilder sb = new StringBuilder();
        ArrayList<String> adminUidList = new ArrayList<>();
        String pictureResult = null;
        adminList.forEach(item -> {
            if (!StringUtils.isEmpty(item.getAvatar())) {
                sb.append(item.getAvatar() + SysConstant.FILE_SEGMENTATION);
            }
            adminUidList.add(item.getUid());
        });
        Map<String, String> pictureMap = new HashMap<>(BlogConstant.NUM_TEN);
        if (!StringUtils.isEmpty(sb)) {
            pictureResult = this.pictureFeignClient.getPicture(sb.toString(), SysConstant.FILE_SEGMENTATION);
        }
        List<Map<String, Object>> picList = webUtil.getPictureMap(pictureResult);
        picList.forEach(item -> {
            pictureMap.put(item.get(SysConstant.UID).toString(), item.get(SysConstant.URL).toString());
        });
        // 3. 获取用户的网盘储存空间


        for (TAdmin item : adminList) {
            TRole role = roleService.getRoleByUid(item.getRoleUid());
            item.setRole(role);
            //获取图片
            if (!StringUtils.isEmpty(item.getAvatar())) {
                List<String> pictureUidsTemp = MyStringUtils.changeStringToStringList(item.getAvatar(), SysConstant.FILE_SEGMENTATION);
                List<String> pictureListTemp = new ArrayList<>();
                pictureUidsTemp.forEach(picture -> {
                    if (pictureMap.get(picture) != null && pictureMap.get(picture) != "") {
                        pictureListTemp.add(pictureMap.get(picture));
                    }
                });
                item.setPhotoList(pictureListTemp);
            }

        }
        return ResultUtils.result(SysConstant.SUCCESS, CommonPage.restPage(adminList));
    }

    @Override
    public String add(AdminAdminVo adminVo) {
        String mobile = adminVo.getMobile();
        String username = adminVo.getUserName();
        String email = adminVo.getEmail();
        if (StringUtils.isEmpty(username)) {
            return ResultUtils.errorWithMessage(MessageConstant.PARAM_INCORRECT);
        }
        if (StringUtils.isEmpty(email) && StringUtils.isEmpty(mobile)) {
            return ResultUtils.errorWithMessage("邮箱和手机号至少一项不能为空");
        }
        TAdminExample example = new TAdminExample();
        example.createCriteria()
                .andUserNameEqualTo(username);
        List<TAdmin> admins = adminMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(admins)) {
            return ResultUtils.result(SysConstant.ERROR, MessageConstant.ENTITY_EXIST);
        }
        String defaultPassword = systemParamService.getSystemParamValueByKey(SysConstant.SYS_DEFAULT_PASSWORD);
        TAdmin admin = new TAdmin();
        admin.setUid(MyStringUtils.getUUID());
        admin.setAvatar(adminVo.getAvatar() + SysConstant.FILE_SEGMENTATION);
        admin.setUserName(username);
        admin.setMobile(mobile);
        admin.setEmail(email);
        admin.setNickName(adminVo.getNickName());
        admin.setRoleUid(adminVo.getRoleUid());
        admin.setGender(adminVo.getGender());
        Date date = new Date();
        admin.setCreateTime(date);
        admin.setUpdateTime(date);

        admin.setStatus(BlogStatus.ENABLE.getStatus());
        admin.setPassWord(passwordEncoder.encode(defaultPassword));
        adminMapper.insertSelective(admin);

        /**
         * TODO 这里需要通过SMS模块，发送邮件告诉初始密码 更新成功后，同时申请网盘存储空间 初始化网盘的容量, 单位 B
         */
        return ResultUtils.successWithMessage(MessageConstant.INSERT_SUCCESS);
    }

    @Override
    public String edit(AdminAdminVo adminVo) {
        TAdmin admin = adminMapper.selectByPrimaryKey(adminVo.getUid());
        if (admin == null) {
            return ResultUtils.errorWithMessage(MessageConstant.PARAM_INCORRECT);
        }
        TAdminExample example = new TAdminExample();
        example.createCriteria()
                .andUserNameEqualTo(adminVo.getUserName());
        List<TAdmin> tAdmins = adminMapper.selectByExample(example);
        for (TAdmin tAdmin : tAdmins) {
            if (!tAdmin.getUid().equals(admin.getUid())) {
                return ResultUtils.errorWithMessage("修改失败，用户名存在");
            }
        }

        if (!StringUtils.isEmpty(adminVo.getUid()) && !adminVo.equals(admin.getUid())) {
            adminCacheService.deleteResourceList(admin.getUid());
            adminCacheService.deleteOnlineAdmin(admin.getUid());
            adminCacheService.deleteToken(admin.getUid());
        }

        TAdmin update = new TAdmin();
        update.setUid(adminVo.getUid());
        update.setAvatar(adminVo.getAvatar() + SysConstant.FILE_SEGMENTATION);
        update.setUserName(adminVo.getUserName());
        update.setNickName(adminVo.getNickName());
        update.setGender(adminVo.getGender());
        update.setRoleUid(adminVo.getRoleUid());
        update.setEmail(adminVo.getEmail());
        update.setQqNumber(adminVo.getQqNumber());
        update.setMobile(adminVo.getMobile());
        update.setOccupation(adminVo.getOccupation());
        update.setUpdateTime(new Date());
        adminMapper.updateByPrimaryKeySelective(update);

        // TODO 更新网盘大小
        return ResultUtils.successWithMessage(MessageConstant.OPERATION_SUCCESS);
    }


    @Override
    public String resetPwd(AdminAdminVo adminVO) {
        String defaultPassword = systemParamService.getSystemParamValueByKey(SysConstant.SYS_DEFAULT_PASSWORD);
        // 获取当前管理员UID
        ServletRequestAttributes attribute = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attribute.getRequest();
        String jwtToken = (String) request.getAttribute(SysConstant.TOKEN);
        String adminUid = jwtTokenUtil.getAdminUid(jwtToken, audience.getBase64Secret());
        TAdmin admin = adminMapper.selectByPrimaryKey(adminUid);
        if (admin == null) {
            return ResultUtils.errorWithMessage(MessageConstant.PARAM_INCORRECT);
        }
        // 判断当前管理员是否是admin
        if (SysConstant.ADMIN.equals(admin.getUserName())
                && !admin.getUid().equals(adminUid)) {
            return ResultUtils.errorWithMessage(MessageConstant.UPDATE_ADMIN_PASSWORD_FAILED);
        }
        admin.setPassWord(passwordEncoder.encode(defaultPassword));
        admin.setUpdateTime(new Date());
        adminMapper.updateByPrimaryKeySelective(admin);
        return ResultUtils.successWithMessage(MessageConstant.UPDATE_SUCCESS);
    }

    @Override
    public String deleteBatchAdmin(List<String> adminUids) {
        boolean check = MyStringUtils.checkUidList(adminUids);
        if (!check) {
            return ResultUtils.errorWithMessage(MessageConstant.PARAM_INCORRECT);
        }
        TAdmin admin = new TAdmin();
        admin.setStatus(BlogStatus.DISABLE.getStatus());
        admin.setUpdateTime(new Date());
        TAdminExample example = new TAdminExample();
        example.createCriteria()
                .andUidIn(adminUids);
        adminMapper.updateByExampleSelective(admin, example);
        return ResultUtils.successWithMessage(MessageConstant.DELETE_SUCCESS);
    }

    @Override
    public String getMe() {
        HttpServletRequest request = RequestHolder.getRequest();
        String token = request.getAttribute(SysConstant.TOKEN).toString();
        String adminUid = jwtTokenUtil.getAdminUid(token, audience.getBase64Secret());
        TAdmin admin = adminMapper.selectByPrimaryKey(adminUid);
        admin.setPassWord(null);
        if (!StringUtils.isEmpty(admin.getAvatar())) {
            String pictureInfo = pictureFeignClient.getPicture(admin.getAvatar(), SysConstant.FILE_SEGMENTATION);
            List<Map<String, Object>> pictureMap = webUtil.getPictureMap(pictureInfo);
            List<String> urlList= new ArrayList<>();
            for (Map<String, Object> item : pictureMap) {
                urlList.add((String) item.get(SysConstant.URL));
            }
            admin.setPhotoList(urlList);
        }
        return ResultUtils.successWithData(admin);
    }

    @Override
    public String editMe(AdminAdminVo adminVO) {
        TAdmin admin = new TAdmin();
        BeanUtils.copyProperties(adminVO, admin);
        admin.setUpdateTime(new Date());
        int result = adminMapper.updateByPrimaryKeySelective(admin);
        if (result > 0) {
            return ResultUtils.successWithMessage(MessageConstant.UPDATE_SUCCESS);
        }
        return ResultUtils.errorWithMessage(MessageConstant.UPDATE_FAIL);
    }

    @Override
    public String changePwd(String oldPwd, String newPwd) {
        HttpServletRequest request = RequestHolder.getRequest();
        String token = request.getAttribute(SysConstant.TOKEN).toString();
        String adminUid = jwtTokenUtil.getAdminUid(token, audience.getBase64Secret());
        if (StringUtils.isEmpty(oldPwd) || StringUtils.isEmpty(newPwd)) {
            return ResultUtils.errorWithMessage(MessageConstant.PARAM_INCORRECT);
        }
        TAdmin admin = adminMapper.selectByPrimaryKey(adminUid);
        boolean matches = passwordEncoder.matches(oldPwd, admin.getPassWord());
        if (matches) {
            admin.setPassWord(passwordEncoder.encode(newPwd));
            admin.setUpdateTime(new Date());
            adminMapper.updateByPrimaryKeySelective(admin);
            adminCacheService.deleteResourceList(adminUid);
            OnlineAdmin onlineAdmin = adminCacheService.getOnlineAdmin(adminUid);
            adminCacheService.deleteToken(onlineAdmin.getTokenUId());
            adminCacheService.deleteOnlineAdmin(adminUid);
            return ResultUtils.successWithMessage(MessageConstant.UPDATE_SUCCESS);
        }
        return ResultUtils.errorWithMessage(MessageConstant.UPDATE_FAIL);
    }

    @Override
    public String getOnlineAdminList(AdminAdminVo adminVO) {
        List<OnlineAdmin> onlineAdminList = adminCacheService.getAllOnlineAdmin();
        Integer pageSize = adminVO.getPageSize();
        Integer currentPage = adminVO.getCurrentPage();
        Integer total = onlineAdminList.size();
        int startIndex = Math.max((currentPage - 1) * pageSize, 0);
        int size = Math.min(startIndex + pageSize, total);
        List<OnlineAdmin> pageList = onlineAdminList.subList(startIndex, size);
        for (OnlineAdmin onlineAdmin : pageList) {
            onlineAdmin.setToken("");
        }
        CommonPage<OnlineAdmin> onlineAdminCommonPage = CommonPage.restPage(pageList);
        onlineAdminCommonPage.setPageNum(currentPage);
        onlineAdminCommonPage.setTotal((long)total);
        return ResultUtils.successWithData(onlineAdminCommonPage);
    }

    @Override
    public String forceLogout(List<String> tokenUidList) {
        System.out.println(tokenUidList);
        for (String tokenUid : tokenUidList) {
            String token = adminCacheService.getToken(tokenUid);
            adminCacheService.deleteOnlineAdmin(token);
            adminCacheService.deleteToken(tokenUid);
        }
        return ResultUtils.successWithData(MessageConstant.OPERATION_SUCCESS);
    }
}
